/*
* name: drag effect
* author : lzc
* date : 2015.05.18
* opts :
*   cntr : contanier class name,id name or dom element,just like ul
*   child : children of contanier class name,tag name ,just like li
*   clickCallBack : callback of mousedown,param( event, $clone: current $element,
*                   $moveChild: movement element ,the copy of $clone )
*   moveCallBack : the callback when mouse move ,param( lastIndex: the index of child which mouse hover )
*   endCallBack : the callback when mouse up
*/
function Drag(opts){
    var $cntr = $(opts.cntr)
    , cntr = {
        width : 0
        , rowNum : 0
        , colNum : 0
    }
    , $child = $cntr.find(opts.child)
    , child = {
        num : $child.length
        , outerWidth : $child.outerWidth(true) //取单元子节点整个width(包括margin值)
        , outerHeight : $child.outerHeight(true)
        , position : 'static'
    }
    , mousedownFlag = false
    , $moveChild = null
    , lastIndex = 0

    function _funcs(){
        function init(){
            cntr.width = $cntr.width()
            cntr.rowNum = Math.floor(cntr.width / child.outerWidth)
            cntr.colNum = Math.ceil(child.num / cntr.rowNum)
        }

        function cntrPosition(){
            $cntr.css('position')=='static' ? $cntr.css('position','releative') : ''
        }
        function staticPosition(){
            $cntr.css('position','static')
        }
        function childPosition($el){
            child.position = $el.css('position')
            $el.css('position','absolute')
            var childIndex = $child.css('z-index')
            $el.css('z-index',childIndex + 10)
        }
        function mouseXYToIndex(x,y){
            var actX = x - $cntr.offset().left//mouse x in $cntr
            var actY = y - $cntr.offset().top//mouse y
            var deltaRow = Math.floor(actX / child.outerWidth - 0.5)
            var deltaCol = Math.floor(actY / child.outerHeight)
            deltaCol > cntr.colNum ? cntr.colNum : deltaCol
            var index = deltaCol * cntr.rowNum + deltaRow
            index = index > child.num ? child.num : index
            if(lastIndex != index){
                lastIndex = index
                insert()
            }
        }
        function movePos(e,$el){
            var mouseX = e.pageX
            , mouseY = e.pageY
            var top = mouseY - child.outerHeight/2
            var left = mouseX - child.outerWidth/2
            $el.offset({top:top,left:left})
            mouseXYToIndex(mouseX,mouseY)
        }
        function insert(){
            if(lastIndex == -1){//Moved to the front of the first child
                $clone.insertBefore($child.eq(0))
            }
            else if(lastIndex == child.num){ //Move to the end
                $clone.insertAfter($child.eq(child.num - 1))
            }
            else{//normal insert
                $clone.insertAfter($child.eq(lastIndex))
            }
        }
        return {
            init : init
            , cntrPosition : cntrPosition
            , staticPosition : staticPosition
            , childPosition : childPosition
            , movePos : movePos
        }
    }
    var funcs = _funcs()
    funcs.init()
    funcs.cntrPosition()
    var $clone
    $child.mousedown(function(e){
        if(!mousedownFlag){
            $child = $cntr.find(opts.child)//每次需要重新获取一下子节点
            $clone = $(this)
            $moveChild = $(this).clone()
            $clone.css('visibility','hidden')
            funcs.childPosition($moveChild)
            $moveChild.appendTo($cntr)
            funcs.movePos(e,$moveChild)//为moveChild定位
            lastIndex = $(this).index()
            mousedownFlag = true
            opts.clickCallBack && opts.clickCallBack(e,$clone,$moveChild)
            return false
        }

    })


    $cntr.on('mousemove',function(e){
        // if(!mousedownFlag) return false
        if(mousedownFlag){
            funcs.movePos(e,$moveChild)
            opts.moveCallBack && opts.moveCallBack(e,$clone,$moveChild,lastIndex)
        }
        return false
    })

    $cntr.mouseup(function(e){
        if(mousedownFlag){
            $clone.css('visibility','visible')
            $moveChild.remove()
            mousedownFlag = false
            opts.endCallBack && opts.endCallBack(e,$clone,$moveChild)
            return false
         }
    })
}